#ifndef TOKENIZER_HPP_
# define TOKENIZER_HPP_

# include <list>
# include <string>

namespace utils {

/*! \class Tokenizer
 * Split a string into tokens separated with specified delimiters
 */
class Tokenizer {
public:
  /*! Token iterator */
  typedef std::list<std::string>::iterator iterator;
  /*! Token const iterator */
  typedef std::list<std::string>::const_iterator const_iterator;
  /*! Token reverse iterator */
  typedef std::list<std::string>::reverse_iterator reverse_iterator;
  /*! Token const reverse iterator */
  typedef std::list<std::string>::const_reverse_iterator const_reverse_iterator;
  /*! The type of the size of the tokens' container */
  typedef std::list<std::string>::size_type size_type;

  /* Construct the object and tokenize the given string
   * \param input: the string to tokenize
   * \param delimiters: the delimiters between each tokens (default: spaces)
   */
  Tokenizer(const std::string &input, const std::string &delimiters = " ");
  /*! Copy constructor
   * \param toCopy : the \a Tokenizer object to copy
   */
  Tokenizer(const Tokenizer &toCopy);
  /*! Destructor */
  ~Tokenizer();

  /*! Asignement operator
   * \param toCopy : the \a Tokenizer object to copy
   * \return A reference on \a this \a Tokenizer object
   */
  Tokenizer &operator=(const Tokenizer &toCopy);

  /* Get the tokens list
   * \return a std::list of tokens
   */
  std::list<std::string> &GetTokensList();

  /* Get the tokens count
   * \return The tokens list's size
   */
  size_type size() const;

  /*! Return iterator to beginning */
  iterator begin();
  /*! Return const iterator to beginning */
  const_iterator begin() const;
  /*! Return reverse iterator to reverse beginning */
  reverse_iterator rbegin();
  /*! Return const reverse iterator to reverse beginning */
  const_reverse_iterator rbegin() const;
  /*! Return iterator to end */
  iterator end();
  /*! Return const iterator to end */
  const_iterator end() const;
  /*! Return reverse iterator to reverse end */
  reverse_iterator rend();
  /*! Return const reverse iterator to reverse end */
  const_reverse_iterator rend() const;

private:
  /*! Check if the character of the input at the position referenced
   * by \a iterator is a delimiter.
   * \param iterator: an iterator on the character to check
   * \return true if the character is a delimiter, otherwise return false
   */
  bool IsADelimiter(std::string::const_iterator &iterator) const;

  /*! Get the next token in the input string
   * \return The next token or an empty string if the end of the input
   * 	     has been reached
   */
  std::string GetNextToken();

  /*! Fill mTokenList with tokens */
  void FillList();

  std::list<std::string> mTokenList;
  std::string mInput; /*!< The string to parse */
  std::string mDelimiters; /*!< The delimiters */
  std::string mToken; /*!< The current token */
  std::string::const_iterator mIterator; /*!< Position in the input */
};

} /* !namespace utils */
#endif /* !TOKENIZER_HPP_ */
